/// @tags: sa
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
using std::max, std::min, std::swap;

typedef long long ll;

int const N = 3e5 + 5;

template <typename T>
inline T &read(T &x) {
  x = 0;
  bool f = false;
  short ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = true;
    ch = getchar();
  }
  while (isdigit(ch)) x = x * 10 + (ch ^ '0'), ch = getchar();
  if (f) x = -x;
  return x;
}

int n, m = 30;
char str[N];
int sa[N], ht[N], rk[N], cnt[N], tmp[N], a[N];
int id[N], f[N], mm[N], mi[N], siz[N];
ll ans[N], ans1[N], ans2[N];

inline void sort() {
  memset(cnt, 0, sizeof(int) * (m + 1));
  for (int i = 1; i <= n; ++i) ++cnt[rk[i]];
  for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
  for (int i = n; i; --i) sa[cnt[rk[tmp[i]]]--] = tmp[i];
}

inline void prework() {
  sort();
  for (int l = 1, p = 0; l <= n; l <<= 1, m = p, p = 0) {
    for (int i = n - l + 1; i <= n; ++i) tmp[++p] = i;
    for (int i = 1; i <= n; ++i)
      if (sa[i] > l) tmp[++p] = sa[i] - l;
    sort();
    memcpy(tmp, rk, sizeof(tmp));
    rk[sa[1]] = p = 1;
    for (int i = 2; i <= n; ++i)
      rk[sa[i]] = (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + l] == tmp[sa[i - 1] + l])
                      ? p
                      : ++p;
  }
  for (int i = 1, j = 0; i <= n; ++i) {
    if (j) --j;
    while (str[i + j] == str[sa[rk[i] - 1] + j]) ++j;
    ht[rk[i]] = j;
  }
}

int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }

inline void merge(int x, int y, int len) {
  x = find(x), y = find(y);
  f[y] = x;
  ans1[len] += 1ll * siz[x] * siz[y];
  siz[x] += siz[y];
  ans[x] = max(ans[x], ans[y]);
  ans[x] = max(ans[x], max(1ll * mm[x] * mm[y], 1ll * mi[x] * mi[y]));
  ans[x] = max(ans[x], max(1ll * mm[x] * mi[y], 1ll * mi[x] * mm[y]));
  mm[x] = max(mm[x], mm[y]);
  mi[x] = min(mi[x], mi[y]);
  ans2[len] = max(ans2[len], ans[x]);
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("P2178 [NOI2015] 品酒大会.in", "r", stdin);
  freopen("P2178 [NOI2015] 品酒大会.out", "w", stdout);
#endif
#endif

  read(n);
  scanf("%s", str + 1);
  for (int i = 1; i <= n; ++i) rk[i] = str[i] - 'a' + 1, tmp[i] = i;
  prework();
  for (int i = 1; i <= n; ++i) read(a[i]), id[i] = i;
  for (int i = 1; i <= n; ++i) f[i] = i, siz[i] = 1, mm[i] = mi[i] = a[i], ans[i] = -1e18;
  memset(ans2, -63, sizeof(ans2));
  std::sort(id + 2, id + n + 1,
            [](int const lhs, int const rhs) -> bool { return ht[lhs] > ht[rhs]; });
  for (int i = 2; i <= n; ++i) merge(sa[id[i]], sa[id[i] - 1], ht[id[i]]);
  for (int i = n; ~i; --i) ans1[i] += ans1[i + 1];
  for (int i = n; ~i; --i) ans2[i] = max(ans2[i], ans2[i + 1]);
  for (int i = 0; i < n; ++i) printf("%lld %lld\n", ans1[i], ans1[i] ? ans2[i] : 0);
  return 0;
}